package org.springframework.samples.petclinic.web;

import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.samples.petclinic.Clinic;
import org.springframework.samples.petclinic.Owner;
import org.springframework.samples.petclinic.Pet;
import org.springframework.samples.petclinic.PetType;
import org.springframework.samples.petclinic.validation.PetValidator;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.SessionAttributes;
import org.springframework.web.bind.support.SessionStatus;
import org.springframework.web.servlet.ajax.json.AjaxContext;

/**
 * JavaBean form controller that is used to add a new <code>Pet</code> to the
 * system.
 *
 * @author Juergen Hoeller
 * @author Ken Krebs
 */
@Controller
@RequestMapping("/addPet.do")
@SessionAttributes("pet")
public class AddPetForm {

	private final Clinic clinic;

	@Autowired
	public AddPetForm(Clinic clinic) {
		this.clinic = clinic;
	}

	@ModelAttribute("types")
	public Collection<PetType> populatePetTypes() {
		return this.clinic.getPetTypes();
	}

    @InitBinder
    public void setAllowedFields(WebDataBinder dataBinder) {
        dataBinder.setDisallowedFields(new String[] {"id"});
    }

    @RequestMapping(method = RequestMethod.GET)
	public String setupForm(@RequestParam("ownerId") int ownerId, Model model) {
		Owner owner = this.clinic.loadOwner(ownerId);
		Pet pet = new Pet();
		owner.addPet(pet);
		model.addAttribute("pet", pet);
		
		if(AjaxContext.isXHR()){
			AjaxContext.getJson().addPartial("popup", "petForm");
			AjaxContext.getJson().addJavascript("$.remoteForm('addOrUpdatePetForm')");
		}
		
		return "petForm";
	}

	@RequestMapping(method = RequestMethod.POST)
	public String processSubmit(@ModelAttribute("pet") Pet pet, BindingResult result, SessionStatus status,
			Model model) {
		new PetValidator().validate(pet, result);
		if (result.hasErrors()) {
			if(AjaxContext.isXHR()){
				AjaxContext.getJson().addPartial("popup", "petForm");
				AjaxContext.getJson().addJavascript("$.remoteForm('addOrUpdatePetForm')");
			}
			return "petForm";
		}
		else {
			this.clinic.storePet(pet);
			status.setComplete();
			
			//TODO build one partial, with key newPartial
			//make another key the index.
			//The javascript will turn the index into an int and insert the partial 
			//after index - 1 or after #afterMe if index-1 < 0
			if(AjaxContext.isXHR()){
								
				//CHUCK TODO Make this nicer.  Don't we do something very similar elsewhere?
				//HEY, the exact same damn thing is in PetAndVisit.java!!
				List<Pet> pets = pet.getOwner().getPets();
				int index = -1;
				for(int i = 0; i < pets.size(); i++){
					if(pets.get(i).getId().equals(pet.getId()))
						index = i;
				}
				if(index == -1)
					throw new RuntimeException("Newly created pet wasn't in owner's pet list!");
				preparePartial(index, model, pet);
				
				//CHUCK TODO!  This is actaully customJavascript, not a real partial.
				//Maybe we shouldn't have so tight control of the keys,
				//and just expect developers to use the correct ones, rather than
				//mandating a key of 'javascript' sometimes.
				//NOTE:  We're relying on the model already having index!
				AjaxContext.getJson().addPartial("customJavascript", "addedPet/removeThenWritePetsJS");

				
			}
			
			return "redirect:owner.do?ownerId=" + pet.getOwner().getId();
		}
	}
	
	//CHUCK TODO REfacto with PetAndVisitDoPartial
	protected void preparePartial(int index, Model model, Pet pet){
		model.addAttribute("index", index);
		model.addAttribute("pet", pet);
		AjaxContext.getJson().addPartial("petAndVisitDiv_" + index, "petAndVisit_");
		
	}

}
